package request.share;

import java.util.Iterator;
import java.util.HashMap;

import soar.basic.*;

public class Stat
{
    private static Stat instance=null;

    private Stat()
    {/*{{{*/
    }/*}}}*/

    public synchronized static Stat getInstance()
    {/*{{{*/
        if(instance == null)
        {
            instance=new Stat();
        }
        return instance;
    }/*}}}*/

    public void init()
    {/*{{{*/
        Cnfg cnfg=Cnfg.getInstance();
        this.workers=new Worker[cnfg.workers];
        for(int i=0; i<this.workers.length; ++i)
        {
            this.workers[i]=new Worker();
        }
        this.svcs=new HashMap<String,Svc>();
    }/*}}}*/

    private class Client
    {/*{{{*/
        public String addr;
        public int call_num;

        Client(String addr)
        {
            this.addr=addr;
            this.call_num=0;
        }
    }/*}}}*/
    private class Worker
    {/*{{{*/
        Client[] clients;
        int client_conn_num;

        Worker()
        {
            this.clients=new Client[Ep.POLL_MAX_NUM];
            this.client_conn_num=0;
        }
    }/*}}}*/
    private Worker[] workers;

    private class Svc
    {/*{{{*/
        int call_num;

        Svc()
        {
            this.call_num=0;
        }
    }/*}}}*/
    private HashMap<String,Svc> svcs;

    public void clientConn(int worker_idx, int slot_id,
            String addr)
    {/*{{{*/
        synchronized(this.workers[worker_idx])
        {
            //System.err.println("client addr: "+addr);
            this.workers[worker_idx].clients[slot_id]=new Client(addr);
            ++this.workers[worker_idx].client_conn_num;
        }
    }/*}}}*/

    public void clientDisconn(int worker_idx, int slot_id)
    {/*{{{*/
        synchronized(this.workers[worker_idx])
        {
            this.workers[worker_idx].clients[slot_id]=null;
        }
    }/*}}}*/

    public void svcCall(String svcname)
    {/*{{{*/
        synchronized(this.svcs)
        {
            Svc svc=this.svcs.get(svcname);
            if(svc == null) 
            {
                svc=new Svc();
            }
            ++svc.call_num;
            svcs.put(svcname, svc);
        }
    }/*}}}*/

    public synchronized String showClients()
    {/*{{{*/
        int client_num=0;
        int client_conn_num=0;
        String response=
            "Client                         Calls\n"+
            "-------                        -------\n";
        for(Worker worker : this.workers)
        {
            for(Client client : worker.clients)
            {
                if(client != null)
                {
                    response+=String.format("%-30s %d\n",
                            client.addr, client.call_num);
                    ++client_num;
                }
            }
            client_conn_num+=worker.client_conn_num;
        }
        response+="-----------\n"+
            String.format("Total: %d\n", client_num);
        response+="-----------\n"+
            String.format("Connected: %d\n", client_conn_num);
        return response;
    }/*}}}*/

    public synchronized String showSvcs()
    {/*{{{*/
        String response=
            "Service                        Calls\n"+
            "-------                        -------\n";
        Iterator it=this.svcs.keySet().iterator();
        while(it.hasNext())
        {
            String svcname=(String)it.next();
            Svc svc=this.svcs.get(svcname);
            response+=String.format("%-30s %d\n", svcname, svc.call_num);
        }
        return response;
    }/*}}}*/
}
